package org.teemor.demo.nio.selector;

import org.junit.Test;
import org.teemor.demo.nio.BaseTest;
import org.teemor.demo.nio.selector.handler.AbstractHandler;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;

/**
 * @Description:
 * @author zhoulk
 * @date: 2020/2/21
 */
public class SelectorServerDemo implements BaseTest {

    @Test
    public void baseTest() throws Exception {
        Selector selector = Selector.open();

        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        serverChannel.configureBlocking(false);
        serverChannel.bind(new InetSocketAddress(8080));
        serverChannel.register(selector, SelectionKey.OP_ACCEPT, new AbstractHandler() {
            @Override
            public void handler(SelectionKey key) {
                System.out.println("一个请求就绪");
                try {

                    SocketChannel socketChannel = ((ServerSocketChannel) key.channel()).accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ, new AbstractHandler() {
                        @Override
                        public void handler(SelectionKey selectionKey) {
                            System.out.println("一个可读事件就绪");
                            ByteBuffer byteBuffer = ByteBuffer.allocate(128);
                            SocketChannel readChannel = (SocketChannel) selectionKey.channel();
                            try {
                                int flag = readChannel.read(byteBuffer);
                                while (flag !=0) {
                                    if (flag > 0) {
                                        byteBuffer.flip();
                                        System.out.println(new String(byteBuffer.array(), StandardCharsets.UTF_8));
                                        byteBuffer.clear();
                                    }
                                    flag = readChannel.read(byteBuffer);
                                }
                                byteBuffer.clear();
                                byteBuffer = ByteBuffer.wrap("response...".getBytes(StandardCharsets.UTF_8));
//                                   byteBuffer.put("response...".getBytes("UTF-8"));
//                                   byteBuffer.flip();
                                SelectionKey writeSelectionKey = readChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE, byteBuffer);
//                                readChannel.write(byteBuffer);
                                syso("connect end");
//                                readChannel.shutdownOutput();
//                                readChannel.close();
//                                selectionKey.cancel();
                                syso("read selectKey:" + selectionKey.toString());
                                syso("write selectKey:" + writeSelectionKey.toString());
                                syso("is equal"+ selectionKey.equals(writeSelectionKey));
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

        while (true) {
            selector.select();
            Set<SelectionKey> selectKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                syso("就绪key："+ selectionKey.toString());
                iterator.remove();
                if (selectionKey.isWritable()) {
                    syso("写事件就绪");
                    ByteBuffer byteBuffer = (ByteBuffer) selectionKey.attachment();
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    syso(new String(byteBuffer.array(), "UTF-8"));
                    socketChannel.write(byteBuffer);
                    socketChannel.close();
                    selectionKey.cancel();
                }else {
                    AbstractHandler handler = (AbstractHandler) selectionKey.attachment();
                    handler.handler(selectionKey);
                }
            }
        }
    }
}
